package com.molichuxing.services.business;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.baidu.aip.ocr.AipOcr;
import com.molichuxing.framework.result.ResponseResult;
import com.molichuxing.framework.utils.FileByteUtil;
import com.molichuxing.services.business.dto.request.create.DrivingLicenseCreateDto;
import com.molichuxing.services.business.dto.response.DriverLicenseDto;
import com.molichuxing.services.business.dto.response.DriverLicenseOcrDto;
import com.molichuxing.services.business.service.DrivingLicenseBizService;
import com.molichuxing.services.infrastructure.dto.request.create.GztDrivingLicenseNotifyLogCreateDto;
import com.molichuxing.services.infrastructure.dto.request.create.GztDrivingLicenseRequestLogCreateDto;
import com.molichuxing.services.infrastructure.dto.request.create.PyDrivingLicenseNotifyLogCreateDto;
import com.molichuxing.services.infrastructure.dto.request.create.PyDrivingLicenseRequestLogCreateDto;
import com.molichuxing.services.infrastructure.service.GztDrivingLicenseNotifyLogService;
import com.molichuxing.services.infrastructure.service.GztDrivingLicenseRequestLogService;
import com.molichuxing.services.infrastructure.service.PyDrivingLicenseNotifyLogService;
import com.molichuxing.services.infrastructure.service.PyDrivingLicenseRequestLogService;
import com.molichuxing.services.sdk.gzt.GztUtil;
import com.molichuxing.services.sdk.py.response.CisReport;
import com.molichuxing.services.sdk.py.response.PyResponseBean;
import com.molichuxing.services.sdk.py.response.driver.DriverLicenseInfo;
import com.molichuxing.services.util.BaiduOCRClient;
import com.molichuxing.services.util.PyParamsUtil;
import com.molichuxing.services.util.Util;

/**
 * 
 * @author liyg
 * 驾驶证服务实现类
 * 2019-09-19
 *
 */
@Service("drivingLicenseBizService")
public class DrivingLicenseBizServiceImpl implements DrivingLicenseBizService{
	
	private static Logger logger = Logger.getLogger(DrivingLicenseBizServiceImpl.class);
	
	@Value("${py.host}")
	private String host;
	@Value("${py.path}")
	private String path;
	@Value("${py.user.id}")
	private String userId;
	@Value("${py.password}")
	private String password;
	@Value("${baidu.drivingLicense.url}")
	private String localFilePath;
	
	@Autowired
	private PyDrivingLicenseRequestLogService pyDrivingLicenseRequestLogService;
	
	@Autowired
	private PyDrivingLicenseNotifyLogService pyDrivingLicenseNotifyLogService;
	
	@Autowired
	private GztDrivingLicenseNotifyLogService gztDrivingLicenseNotifyLogService;
	
	@Autowired
	private GztDrivingLicenseRequestLogService gztDrivingLicenseRequestLogService;
	
	/**
	 * 获取驾驶证接口
	 * @param createDto
	 * @return
	 */
	@Override
	public ResponseResult<DriverLicenseDto> getDrivingLicense(DrivingLicenseCreateDto createDto) {
		//保存日志信息
		Integer requestId = saveRequestPy(createDto);
		String result=null;
		try {
			String param = PyParamsUtil.getDrivingLicense(createDto.getRealName(),createDto.getIdNumber());
			result = PyParamsUtil.requestApi(host, path, userId, password, param);
		} catch (Exception e) {
			logger.error("鹏元驾驶证接口异常:",e);
			PyDrivingLicenseNotifyLogCreateDto logCreateDto=new PyDrivingLicenseNotifyLogCreateDto();
			logCreateDto.setRequestId(requestId);
			logCreateDto.setExternalStatus("500");
			logCreateDto.setExternalErrorMessage("鹏元驾驶证接口异常");
			pyDrivingLicenseNotifyLogService.create(logCreateDto);
			return getGztData(createDto);
		}
		
		ResponseResult<DriverLicenseDto> response = getPyResult(createDto,result,requestId);
		if(response.getCode().equals(110)) {
			return getGztData(createDto);
		}
		return response;
	}
	
	
	/**
	 * 获取驾驶证接口(国政通)
	 * @param dto
	 * @return
	 */
	@Override
	public ResponseResult<DriverLicenseDto> getGztDrivingLicense(DrivingLicenseCreateDto dto) {
		//保存日志信息
		Integer requestId = saveRequestGzt(dto);
		String result =null;
		try {
			// 国政通接口验证驾驶证
			GztUtil.getClient();
			result = GztUtil.verifyDrivingLicense(dto.getRealName(), dto.getIdNumber());
			logger.info("国政通调用驾驶证信息 》》》》》》》》出参:" + result);
		} catch (Exception e) {
			logger.error("国政通接口验证驾驶证异常：", e);
			GztDrivingLicenseNotifyLogCreateDto createDto=new  GztDrivingLicenseNotifyLogCreateDto();
			createDto.setRequestId(requestId);
			createDto.setExternalStatus("500");
			createDto.setErrorValue("调用国政通三要素接口异常");
			gztDrivingLicenseNotifyLogService.create(createDto);
			return getGztError();
		}
		return getGztResult(dto,result,requestId);		
	}
	
	/**
	 * 获取国政通驾驶证验证接口
	 * @param dto
	 * @return
	 */
	private ResponseResult<DriverLicenseDto> getGztData(DrivingLicenseCreateDto dto) {
		//保存日志信息
		Integer requestId = saveRequestGzt(dto);
		String result =null;
		try {
			// 国政通接口验证驾驶证
			GztUtil.getClient();
			result = GztUtil.verifyDrivingLicense(dto.getRealName(), dto.getIdNumber());
			logger.info("国政通调用驾驶证信息 》》》》》》》》出参:" + result);
		} catch (Exception e) {
			logger.error("国政通接口验证驾驶证异常：", e);
			GztDrivingLicenseNotifyLogCreateDto createDto=new  GztDrivingLicenseNotifyLogCreateDto();
			createDto.setRequestId(requestId);
			createDto.setExternalStatus("500");
			createDto.setErrorValue("调用国政通三要素接口异常");
			gztDrivingLicenseNotifyLogService.create(createDto);
			return getGztError();
		}
		return getGztResult(dto,result,requestId);
	}
	
	/**
	 * 获取国政通驾驶证结果
	 * @param dto
	 * @param result
	 * @param requestId
	 * @return
	 */
	private ResponseResult<DriverLicenseDto> getGztResult(DrivingLicenseCreateDto dto,String result,Integer requestId){
		GztDrivingLicenseNotifyLogCreateDto createDto=new  GztDrivingLicenseNotifyLogCreateDto();
		    createDto.setExternalResponse(result);
		    createDto.setRequestId(requestId);
		    if(StringUtils.isBlank(result)) {
				createDto.setExternalStatus("500");
				createDto.setErrorValue("调用国政通驾驶证接口返回数据为空");
				gztDrivingLicenseNotifyLogService.create(createDto);
				return getGztError();
			}
		    
		    Document doc=null;
			try {
				doc = DocumentHelper.parseText(result);
			} catch (DocumentException e) {
				createDto.setExternalStatus("500");
				createDto.setErrorValue("解析国政通三要素接口返回xml异常");
				return getGztError();
			}
		    Element root = doc.getRootElement();
	        Element mesElement=root.element("message");
	        Element statusElement=mesElement.element("status");
	        String status=statusElement.getStringValue();
	        createDto.setExternalStatus(status);
	        Element valueElement=mesElement.element("value");
	        String value=valueElement.getStringValue();
	        createDto.setErrorValue(value);
	       //0  处理成功 
	       if("0".equals(status)) {
	        	Element jszcsElement = root.element("jszcs");
	        	Element jszcElement = jszcsElement.element("jszc");
	        	Element wybsElement = jszcElement.element("wybs");
	        	String wybs = wybsElement.getStringValue();
	        	createDto.setWybs(wybs);
	        	Element codeElement = jszcElement.element("code");
	        	String code = codeElement.getStringValue();
	        	createDto.setCode(code);
	        	Element messageElement= jszcElement.element("message");
	        	String message = messageElement.getStringValue();
	        	createDto.setMessage(message);
	        	//1：请求成功_有结果 0：请求成功_无结果 -999：参数格式错误或其它错误 -990：接口调用失败  
	        	if(StringUtils.isBlank(code) || !"1".equals(code)) {
	        		gztDrivingLicenseNotifyLogService.create(createDto);
	        		return getGztError();
	        	}
	        
	        	//获取国政通数据
	            DriverLicenseDto driverLicenseDto=getGztDriverLicense(jszcElement,createDto);
	        	Element zt = jszcElement.element("zt");//状态
	        	String ztValue=zt.getStringValue();
	        	if(!Util.validatePassTypeGzt(ztValue)) {
	        		gztDrivingLicenseNotifyLogService.create(createDto);
	        		return getError(driverLicenseDto);
	        	}
	        	Element zjcx = jszcElement.element("zjcx");//准驾车型
	        	String zjcxValue=zjcx.getStringValue();
	        	if(!Util.verificationDriverLicense(zjcxValue)) {
	        		gztDrivingLicenseNotifyLogService.create(createDto);
	        		return getError(driverLicenseDto);
	        	}
	        	gztDrivingLicenseNotifyLogService.create(createDto);
	        	// 验证状态（0: 验证失败 ，1：验证通过，2：待验证）
	        	driverLicenseDto.setStatus(1);
	 	        return new ResponseResult<DriverLicenseDto>().success(driverLicenseDto);
	        }else {
	        	gztDrivingLicenseNotifyLogService.create(createDto);
	        	return getGztError();
	        }
	}
	
	/**
	 * 获取国政通数据
	 * @param jszcElement
	 * @param createDto
	 * @return
	 */
	 private DriverLicenseDto getGztDriverLicense(Element jszcElement,GztDrivingLicenseNotifyLogCreateDto createDto) {
         Element inputJszh = jszcElement.element("inputZjhm"); //驾驶证号
         Element inputXm = jszcElement.element("inputXm");//姓名
         Element zt = jszcElement.element("zt");//状态
         Element ljjf = jszcElement.element("ljjf");//累计积分
         Element zjcx = jszcElement.element("zjcx");//准驾车型
         Element qfrq = jszcElement.element("qfrq");//签发日期
         Element qsyxq = jszcElement.element("qsyxq");//起始有效期
         Element jsyxq = jszcElement.element("jsyxq");//结束有效期
         Element dabh = jszcElement.element("dabh");//结束有效期

         DriverLicenseDto dto=new DriverLicenseDto();
         String inputJszhValue=inputJszh.getStringValue();
         createDto.setInputJszh(inputJszhValue);
         String inputXmValue=inputXm.getStringValue();
         createDto.setInputXm(inputXmValue);
         String ztValue=zt.getStringValue();
         createDto.setZt(ztValue);
         String ljjfValue=ljjf.getStringValue();
         createDto.setLjjf(ljjfValue);
         dto.setScore(ljjfValue);
         String zjcxValue=zjcx.getStringValue();
         createDto.setZjcx(zjcxValue);
         dto.setCarClass(zjcxValue);
         String qfrqValue=qfrq.getStringValue();
         createDto.setQfrq(qfrqValue);
         dto.setIssueDate(qfrqValue);
         String qsyxqValue=qsyxq.getStringValue();
         createDto.setQsyxq(qsyxqValue);
         String jsyxqValue=jsyxq.getStringValue();
         createDto.setJsyxq(jsyxqValue);
         dto.setExpiryDate(jsyxqValue);
         String dabhValue = dabh.getStringValue();
         createDto.setDabh(dabhValue);
         dto.setFileNo(dabhValue);
         dto.setStatus(0);
         return dto;
	}
	

	/**
	 * 获取鹏元数据结果
	 * @param dto
	 * @param result
	 * @param requestId
	 * @return
	 */
	private ResponseResult<DriverLicenseDto> getPyResult(DrivingLicenseCreateDto dto,String result,Integer requestId){
		PyDrivingLicenseNotifyLogCreateDto createDto=new PyDrivingLicenseNotifyLogCreateDto();
		createDto.setRequestId(requestId);
		if(StringUtils.isBlank(result)) {
			createDto.setExternalStatus("500");
			createDto.setExternalErrorMessage("调用鹏元驾驶证接口返回数据为空");
			pyDrivingLicenseNotifyLogService.create(createDto);
			return getGztError();
		}
		
		PyResponseBean pyResponseBean = JSONObject.parseObject(result, PyResponseBean.class);
		
		//保存鹏元返回参数
		savePyRespone(pyResponseBean,result,requestId);
		
		if (null != pyResponseBean && "1".equals(pyResponseBean.getStatus())) {
			List<CisReport> cisReports = pyResponseBean.getReturnValue().getCisReport();
			if(null == cisReports || cisReports.isEmpty()) {
				logger.error("《鹏元》  鹏元cisReports为空");
				return getGztError();
			}
			
			for (CisReport cisReport : cisReports) {
				if ("true".equals(cisReport.getHasSystemError()) || "true".equals(cisReport.getIsFrozen())) {
					logger.error("《鹏元》  鹏元系统错误||该客户是否被冻结");
					return getGztError();
				}
				
				DriverLicenseInfo driverLicenseInfo = cisReport.getDriverLicenseInfo();
				if(null == driverLicenseInfo) {
					logger.error("《鹏元》 mobileCheckInfo为空");
					return getGztError();
				}
				
				DriverLicenseDto driverLicenseDto = saveDriverLicenseDto(driverLicenseInfo);
				// status 验证状态（0: 验证失败 ，1：验证通过，2：待验证）
				driverLicenseDto.setStatus(0);
				
				// 1：查得，2：未查得，3：其它原因未查得
				Integer treatResult =driverLicenseInfo.getTreatResult();
				if(null == treatResult || treatResult != 1) {
					logger.error("《鹏元》 子报告查询状态  未查得");
					return getGztError();
				}
				
				//是否有驾照，1-是，0-否
				if (0 == driverLicenseInfo.getHasLicense()) {
					logger.info("《鹏元》驾驶证查询 无驾照");
					return getGztError();
				}
				if(!Util.verificationDriverLicense(driverLicenseInfo.getCarClass())) {
					logger.info("《鹏元》驾驶证查询 准驾车型未通过");
					return getError(driverLicenseDto);
				}
				if(!Util.validatePassType(driverLicenseInfo.getStatus())) {
					logger.info("《鹏元》驾驶证查询 驾驶证状态未通过");
					return getError(driverLicenseDto);
				}
				// status 验证状态（0: 验证失败 ，1：验证通过，2：待验证）
				driverLicenseDto.setStatus(1);
				return new ResponseResult<DriverLicenseDto>().success(driverLicenseDto);
			}
		} 
		
		return getGztError();
	}
	
	/**
	 * 保存驾驶证信息
	 * @param driverLicenseInfo
	 * @return
	 */
	private DriverLicenseDto  saveDriverLicenseDto(DriverLicenseInfo driverLicenseInfo) {
		DriverLicenseDto driverLicenseDto=new  DriverLicenseDto();
		driverLicenseDto.setCarClass(driverLicenseInfo.getCarClass());
		driverLicenseDto.setScore(driverLicenseInfo.getScore());
		driverLicenseDto.setIssueDate(driverLicenseInfo.getIssueDate());
		driverLicenseDto.setExpiryDate(driverLicenseInfo.getExpiryDate());
		driverLicenseDto.setFileNo(driverLicenseInfo.getFileNo());
		driverLicenseDto.setIssuePlace(driverLicenseInfo.getIssuePlace());
		return driverLicenseDto;
	}
	
	/**
	 * 保存请求鹏元日志(鹏元驾驶证)
	 * @param realName
	 * @param idNumber
	 * @param phone
	 * @return
	 */
	private Integer saveRequestPy(DrivingLicenseCreateDto dto){
		PyDrivingLicenseRequestLogCreateDto createDto=new PyDrivingLicenseRequestLogCreateDto();
		createDto.setUserId(dto.getIdNumber());
		createDto.setUserName(dto.getRealName());
		return pyDrivingLicenseRequestLogService.create(createDto);
	}
	
	/**
	 * 保存请求国政通日志(鹏元驾驶证)
	 * @param realName
	 * @param idNumber
	 * @param phone
	 * @return
	 */
	private Integer saveRequestGzt(DrivingLicenseCreateDto dto){
		GztDrivingLicenseRequestLogCreateDto createDto=new GztDrivingLicenseRequestLogCreateDto();
		createDto.setIdNumber(dto.getIdNumber());
		createDto.setFullName(dto.getRealName());
		return gztDrivingLicenseRequestLogService.create(createDto);
	}
	
	/**
	 * 保存鹏元驾驶证返回的数据
	 * @param py
	 * @param result
	 * @param requestId
	 */
	private void savePyRespone(PyResponseBean py,String result, Integer requestId) {
		PyDrivingLicenseNotifyLogCreateDto createDto=new PyDrivingLicenseNotifyLogCreateDto();
		createDto.setRequestId(requestId);
		createDto.setExternalStatus(py.getStatus());
		createDto.setExternalErrorMessage(py.getErrorMessage());
		createDto.setExternalErrorCode(py.getErrorCode());
		createDto.setExternalResponse(result);
		if(null != py && "1".equals(py.getStatus())) {
			List<CisReport> cisReports = py.getReturnValue().getCisReport();

			DriverLicenseInfo driverLicenseInfo = null;
			if(null != cisReports && cisReports.size()>0) {
				CisReport cisReport = cisReports.get(0);
				createDto.setIsFrozen(cisReport.getIsFrozen());
				createDto.setHasSystemError(cisReport.getHasSystemError());
			    driverLicenseInfo = cisReport.getDriverLicenseInfo();
			}
			
			if(null != driverLicenseInfo) {
				createDto.setTreatResult(driverLicenseInfo.getTreatResult());
				createDto.setErrorMessage(driverLicenseInfo.getErrorMessage());
				createDto.setTreatErrorCode(driverLicenseInfo.getTreatErrorCode());
				createDto.setHasLicense(driverLicenseInfo.getHasLicense());
				createDto.setCarClass(driverLicenseInfo.getCarClass());
				createDto.setScore(driverLicenseInfo.getScore());
				createDto.setIssueDate(driverLicenseInfo.getIssueDate());
				createDto.setExpiryDate(driverLicenseInfo.getExpiryDate());
				createDto.setFileNo(driverLicenseInfo.getFileNo());
				createDto.setIssuePlace(driverLicenseInfo.getIssuePlace());
				createDto.setStatus(driverLicenseInfo.getStatus());
			}
		}
		pyDrivingLicenseNotifyLogService.create(createDto);
	}

	
	/**
	 * 获取错误信息
	 * @return
	 */
	private ResponseResult<DriverLicenseDto> getGztError(){
		return new ResponseResult<>(110, "调用国政通接口", null);
	}
	/**
	 * 获取错误信息
	 * @return
	 */
	private ResponseResult<DriverLicenseDto> getError(DriverLicenseDto driverLicenseDto){
		return new ResponseResult<>(1, "抱歉，您的驾驶证未通过验证", driverLicenseDto);
	}
	
	/**
	 * 获取驾驶证接口(ocr)
	 * @param faceUrl
	 * @return
	 */
	@Override
	public ResponseResult<DriverLicenseOcrDto> getOcrDrivingLicense(String faceUrl) {
		//获取ocr数据
		org.json.JSONObject json = baiduOcr(faceUrl);
		return getOcrResult(json);
	}
	
	/**
	 * 获取ocr识别结果
	 * @param faceUrl
	 * @return
	 */
	private org.json.JSONObject baiduOcr(String faceUrl){
        String localFileUrl = localFilePath+ File.separator+UUID.randomUUID()+".jpg";
        FileByteUtil.saveLocalFile(faceUrl,localFileUrl);
        AipOcr client = BaiduOCRClient.getInstance();
        HashMap<String, String> options = new HashMap<String, String>();
        options.put("detect_direction", "true");
        org.json.JSONObject json = client.drivingLicense(localFileUrl, options);
        FileByteUtil.deleteFile(localFileUrl);
        return json;
    }
	
	/**
	 * 解析ocr数据
	 * @param json
	 * @return
	 */
	private ResponseResult<DriverLicenseOcrDto> getOcrResult(org.json.JSONObject orgJson) {
		String jsonStr = orgJson.toString();
		logger.info("ocr返回结果数据:"+jsonStr);
		DriverLicenseOcrDto ocrDto =new  DriverLicenseOcrDto();
		ocrDto.setStatus(0);
		JSONObject  json = JSONObject.parseObject(jsonStr);
		Object errorCode = json.get("error_code");
		if(null != errorCode) {
			logger.info("ocr 错误code:"+errorCode);
			return getOcrError(ocrDto);
		}
		
		JSONObject jsonObject = json.getJSONObject("words_result");
		String licenseCode = jsonObject.getJSONObject("证号").getString("words");
		ocrDto.setLicenseCode(licenseCode);
		String model = jsonObject.getJSONObject("准驾车型").getString("words");
		ocrDto.setModel(model);
		String address = jsonObject.getJSONObject("住址").getString("words");
		ocrDto.setAddress(address);
		String name = jsonObject.getJSONObject("姓名").getString("words");
		ocrDto.setName(name);
		String nationality = jsonObject.getJSONObject("国籍").getString("words");
		ocrDto.setNationality(nationality);
		String sex = jsonObject.getJSONObject("性别").getString("words");
		ocrDto.setSex(1);
		if(StringUtils.isNoneBlank(sex)) {
			ocrDto.setSex(sex.equals("男") ? 1 : 0 );
		}
		
		if(StringUtils.isBlank(model)) {
			logger.info("ocr 准驾车型不满足条件");
			return getOcrError(ocrDto);
		}
		if(!Util.verificationDriverLicense(model)) {
			logger.info("ocr 准驾车型不满足条件");
			return getOcrError(ocrDto);
		}
		return getOcrSuccess(ocrDto);
	}
	
	
	/**
	 * 获取ocr
	 * @return
	 */
	private ResponseResult<DriverLicenseOcrDto> getOcrSuccess(DriverLicenseOcrDto ocrDto){
		return new ResponseResult<DriverLicenseOcrDto>().success(ocrDto);
	}
	
	/**
	 * 获取ocr
	 * @return
	 */
	private ResponseResult<DriverLicenseOcrDto> getOcrError(DriverLicenseOcrDto ocrDto){
		return  new ResponseResult<DriverLicenseOcrDto>(1, "抱歉，您的驾驶证未通过验证", ocrDto);
	}
	
}
